/**
 * Copyright © 2014-2015 珍药材版权所有 ICP备14019602号-3
 */
package calvin.study.rabbitmq.service.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

public class BaseService {

	private static final Logger logger = LoggerFactory.getLogger(BaseService.class);

	@Autowired
	private TransactionTemplate transactionTemplate;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	/**
	 * @return the transactionTemplate
	 */
	public TransactionTemplate getTransactionTemplate() {
		return transactionTemplate;
	}

	protected Exception setException(Exception e) {
		return new Exception("系统发生异常，异常信息：" + e.getMessage());
	}

	/**
	 * 执行较复杂事物处理使用的方法（比如某个业务逻辑处理完成后，需要发送短信，微信推送，向消息队列中打消息等等）
	 * 
	 * @param tr
	 * @throws Exception 请直接抛出异常，不要捕获，否则事务无法回滚
	 */
	protected Object execute(TransactionService tr) throws Exception {
		return execute(tr, true);
	}

	/**
	 * 执行较复杂事物处理使用的方法（比如某个业务逻辑处理完成后，需要发送短信，微信推送，向消息队列中打消息等等）
	 * 
	 * @param tr
	 * @param doExceptFlag 是否执行业务逻辑外的处理(true：执行；false：不执行)
	 * @return
	 * @throws Exception
	 */
	protected Object execute(final TransactionService tr, boolean doExceptFlag) throws Exception {
		final Object obj = getTransactionTemplate().execute(new TransactionCallback<Object>() {
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try {
					return tr.doTransaction();
				} catch (Exception e) {
					status.setRollbackOnly();
					return setException(e);
				}
			}
		});
		if (obj instanceof Exception) {
			Exception ex = (Exception) obj;
			throw ex;
		} else {
			if (doExceptFlag) {
				try {
					taskExecutor.execute(new Runnable() {
						@Override
						public void run() {
							tr.doExceptTransaction(obj);
						}
					});
				} catch (Exception e) {
					logger.error("execute方法的事物外执行程序出错，错误信息：", e);
				}
			}
		}
		return obj;
	}

	public interface TransactionService {
		/**
		 * 实现正常事物业务逻辑
		 * 
		 * @return 根据自己的实际需要，返回值，该值将作为doExceptTransaction方法的参数
		 * @throws Exception
		 */
		Object doTransaction() throws Exception;

		/**
		 * 实现正常事物之外的业务逻辑（比如发送短信，微信推送，向消息队列中打消息等等）
		 * 
		 * @param obj
		 */
		void doExceptTransaction(Object obj);
	}

	/**
	 * 将源对象的属性复制到目标对象中<br>
	 * 注意：该方法只针对于符合javabean规范的类，而且属性的类型是基础类型或其包装类。<br>
	 * 另外，只有属性名和类型匹配的才能复制，否则不能。对于不能复制的，请手动通过get/set方式<br>
	 * 来完成复制过程。该方法也不支持Date类型的复制，使用时请注意，以免出现问题。
	 * 
	 * @Date 2016年5月31日
	 * @param source 源对象
	 * @param target 目标对象
	 */
	public void copyPropertys(Object source, Object target) {
		BeanUtils.copyProperties(source, target);
	}
}
